/*
 *   This program is part of FXPointer.
 *   
 *   FXPointer is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * The Initial Developer of the Original Code is
 * Jeff Schiller
 *
 * Portions created by the Initial Developer are Copyright (C) 2007
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 * Jeroen Hoekx
 */ 
 
function inspect(obj) {
    var str = new Array();
    for(element in obj) { str[str.length] = element; }
    str.sort();
    alert(obj + ":" + str.join(' '));
}

var FXPointer = {
  onClickLink: function(evt) {
    // get the link's href (evt.target)
    // parse into URL and #fragment
    // TODO: fix this in case there is an escaped # in the fragment (use indexOf() and substr())
    var destURL = evt.target.toString().split("#");
    // if no #fragment, then return
    if(destURL.length == 1) { return; }
    
    var curwin = gBrowser.selectedBrowser.contentDocument.defaultView;
    if(!curwin) { return; }
    
    var curURL = curwin.location.toString().split("#");

    // if document is not the same as the currently selected browser's location, then return
    if(curURL[0] !== destURL[0]) { return; }
    
    document.getElementById('urlbar').evalXPointer(gBrowser.selectedBrowser.contentDocument, destURL[1]);
  },
  
  onLoad: function() {
    // initialization code
    var sss = Components.classes["@mozilla.org/content/style-sheet-service;1"]
                    .getService(Components.interfaces.nsIStyleSheetService);
    var ios = Components.classes["@mozilla.org/network/io-service;1"]
                    .getService(Components.interfaces.nsIIOService);
    var uri = ios.newURI("chrome://fxpointer/content/content.css", null, null);
    if(!sss.sheetRegistered(uri, sss.USER_SHEET))
        sss.loadAndRegisterSheet(uri, sss.USER_SHEET);
        
    document.addEventListener("XPointerClickEvent", this.onClickLink, false, true);
        
    this.initialized = true;

    gBrowser.addEventListener("load", function(evt) { 
        // evt.originalTarget is the document that is being loaded
        document.getElementById("urlbar").evalXPointer(evt.originalTarget, null);
    }, true);
  },

  /*
  onMenuItemCommand: function() {
    window.open("chrome://fxpointer/content/fxpointer.xul", "", "chrome");
  },
  */
  
  onCopyXPointerElementLink: function(e) {
    if(!e) { return; }
    // strip off any existing hash, then append our new element() string
    var elStr = window.content.location.href.split("#")[0] + "#" + this.findElemString(e, "");
//    var clipboard = gContextMenu.getService('@mozilla.org/widget/clipboardhelper;1', Components.interfaces.nsIClipboardHelper);
    var clipboard = Components.classes["@mozilla.org/widget/clipboardhelper;1"].
                                    getService(Components.interfaces.nsIClipboardHelper);
    clipboard.copyString( elStr );    
  },
  
  findElemString: function(node, strChild) {
    if(!node) { 
        return strChild; 
    }
    
    // TODO: check for the actual documentElement, not the <HTML> tag
    // (see if this doesn't work for html embedded inside html (iframe, object, etc)
    if( "HTML" == node.tagName.toUpperCase() ) {
        return "element(/1" + strChild + ")";
    }
    
    var id = node.getAttribute("id");
    if(id != null && id != "") {
        // if we can link directly to an ID, then let's use the common URL syntax
        // and don't go down the XPointer element() route
        if(strChild == null || strChild == "") {
            return id;
        }
        
        // This isn't strictly necessary anymore since I don't allow 
        // creation of XPointer element links with trailing 1's
        
        // find all the node numbers
        var nodeNumbers = strChild.split("/");
        // if we get all 1's (/1/1/1/1) then just return the id, 
        // otherwise return the element(id/x/y/z) string
        for(var i = 0; i < nodeNumbers.length; ++i) {
            if(nodeNumbers[i] && nodeNumbers[i] != "" && nodeNumbers[i] != "1") {
                return "element(" + id + strChild + ")";
            }
        }
        return id;
    }
    
    var sibNum = 1;
    var tempNode = node;
    while(tempNode.previousSibling) {
        if(tempNode.previousSibling.nodeType == 1) {
            sibNum++;
        }
        tempNode = tempNode.previousSibling;
    }
    var str = "";
    // swallow any trailing 1's (we prefer shorter XPointer links in general)
    if(sibNum > 1) {
        str = "/"+sibNum+strChild;
    }
    if(node.parentNode) {
        return this.findElemString(node.parentNode,str);
    }
    return str;
  }
  
  
};

window.addEventListener("load", function(e) { FXPointer.onLoad(e); }, false); 
